/*
 ####        # 
 #           #
 ## ### #  # #
 #  #-# #\ # #
 #  # # # \# ####
 Author: Felipe de Andrade Neves Lavratti

 Copyright: There are no restrictions. Use as you want.	  
*/


#include "lpc_config.h"

#include "uart/uart.h"
#include "mprintf/mprintf.h"
#include "timer/timer.h"

#include "lcd/lcd_driver.h"
#include "lcd/pic/SELivre-LTF430-Logo.h"
#include "./swim/lpc_swim.h"
#include "./swim/lpc_swim_font.h"
#include "./swim/lpc_winfreesystem14x16.h"

#include "touchscreen/touchscreen.h"

#include "sdram/sdram.h"


/* Function prototypes */
void PLLInit( void );
void GPIOInit(void);
void App(void);
void Console(void);

void putc_uart0(char c)
{
	UARTTransmitByte(c,UART_CH_0);
}


SWIM_WINDOW_T win1[5], win2[5], win3[5];
SWIM_WINDOW_T *STDOUT_win;
COLOR_T *lcd_page_0, *lcd_page_1, *lcd_page_2, *lcd_page_3;


/* Main function only does the peripherical initialization and setup the pointer to the lcd pages. */
int main( void )
{
	int c;

	STDOUT_win = &win2[0];

	PLLInit();
	GPIOInit();

	UARTInit(9600,UART_CH_0,0);


	SDRAM_Init();

//	if (TRUE == SDRAM_Test()) printf("-- Sdram Test: OK\n");
//	else printf("-- Sdram Test: FAIL\n");

	LCD_Ctrl (FALSE);
	delayMs(100);
	LCD_Init (NULL, NULL, 0);
	LCD_Change_Page (LogoPic.pPicStream, 0);

//	LCD_Cursor_Dis(0);
//	LCD_Copy_Cursor ((UNS_32 *)Cursor, 0, sizeof(Cursor)/sizeof(UNS_32));
//	LCD_Cursor_Cfg(CRSR_FRAME_SYNC | CRSR_PIX_64);
//	LCD_Cursor_En(0);
	LCD_Ctrl (TRUE);

	lcd_page_0 = (COLOR_T *)LCD_VRAM_BASE_ADDR;
	lcd_page_1 = (COLOR_T *)(LCD_VRAM_BASE_ADDR + C_LCD_PAGE_SIZE);
	lcd_page_2 = (COLOR_T *)(LCD_VRAM_BASE_ADDR + 2*C_LCD_PAGE_SIZE);
	lcd_page_3 = (COLOR_T *)(LCD_VRAM_BASE_ADDR + 3*C_LCD_PAGE_SIZE);

	App();
	//Console();

	return 0;
}

/* This function fill a LCD framebuffer page (COLOR_T *pag) using the SWIM. 
   It creates a main window (winbuf[0]) plus 4 simple buttons (winbuf[1]-[3])*/ 
void ScreenSetWindows(SWIM_WINDOW_T *winbuf, COLOR_T *pag, COLOR_T cor_main_0, COLOR_T cor_main_1, COLOR_T cor_main_2, const UNS_8 *title)
{
	swim_window_open(&winbuf[0],
					 C_LCD_H_SIZE, C_LCD_V_SIZE,
					 pag,
					 0, 0,  C_LCD_H_SIZE-101 , C_LCD_V_SIZE -1,
					 3,	cor_main_0, cor_main_1, cor_main_2);
	swim_set_title(&winbuf[0], title, 0x0000);

	swim_window_open(&winbuf[1], // orange
					 C_LCD_H_SIZE, C_LCD_V_SIZE,
					 pag,
					 380, 0,  C_LCD_H_SIZE -1 , 68 -1,
					 5,	0x7900, 0xf980, BLACK);

	swim_window_open(&winbuf[2], //blue
					 C_LCD_H_SIZE, C_LCD_V_SIZE,
					 pag,
					 380, 68,  C_LCD_H_SIZE-1 , 136-1,
					 5,	0x000f, 0x001f, BLACK);

	swim_window_open(&winbuf[3], //red
					 C_LCD_H_SIZE, C_LCD_V_SIZE,
					 pag,
					 380, 136,  C_LCD_H_SIZE-1 , 204-1,
					 5,	0x4000, 0xf800, BLACK);

	swim_window_open(&winbuf[4], //green
					 C_LCD_H_SIZE, C_LCD_V_SIZE,
					 pag,
					 380, 204,  C_LCD_H_SIZE-1 , 272-1,
					 5,	0x0200, 0x07e0, BLACK);
}

/* This is a function that process the coordinates x,y of the touch, and then set a variable
   if the touch has happened over one of the 4 buttons */
int TouchProcess(touchscreen_data *ts, int *tela)
{
	if (ts->x >= 380 && ts->x <= 480)
	{
		if (ts->y >= 0 && ts->y <= 67)
		{
			*tela=0;
			return 1;
		}
		if (ts->y >= 68 && ts->y <= 135)
		{
			*tela=1;
			return 1;
		}
		if (ts->y >= 136 && ts->y <= 203)
		{
			*tela=2;
			return 1;
		}
		if (ts->y >= 204 && ts->y <= 271)
		{
			*tela=3;
			return 1;
		}
	}
	return 0;
}

/* This is the application function, it does only fill the lcd framebuffer page with the windows and
   monitor for touch at the touchpannel */
void App()
{
	float c;
	char car;
	char buf2[10];
	char buf[100];
	int screen=0;
	int i;
	int line[17], col[4];

	for(i=0; i<18; i++) line[i] = (i * 16);
	for(i=0; i<4; i++)  col[i]  = i * 125;


	unsigned int cursor_x, cursor_y;
	touchscreen_data ts_data;

	ScreenSetWindows(win1, lcd_page_1, (COLOR_T)BLUE, (COLOR_T)BLACK, (COLOR_T)BLUE, "UART Console!");
	ScreenSetWindows(win2, lcd_page_2, (COLOR_T)0xf800, (COLOR_T)BLACK, (COLOR_T)0xf800,"Window Red!");
	ScreenSetWindows(win3, lcd_page_3, (COLOR_T)0x07e0, (COLOR_T)BLACK, (COLOR_T)0x07e0, "Window Green!");
	for(i=0;i<15;i++) swim_put_text_xy(&win2[0], "Ola Mundo!", col[i%3], line[i]);
	for(i=0;i<15;i++) swim_put_text_xy(&win3[0], "Hello World!", col[i%3], line[i]);



	while (1)
	{
		switch(screen)
		{
		case 0:
			LCD_Change_Page(NULL,0);
			while(screen==0)
			{
				if(TSGetTouch(1, &ts_data))
				{
					if (ts_data.x >= 190 && ts_data.x <= 300)
						{
							if (ts_data.y >= 96 && ts_data.y <= 176) screen = 3;
						}
				}
			}
			break;

		case 1:
			LCD_Change_Page(NULL,1);
			i=0;
			while(screen==1)
			{
				if(UARTIsDataReady(UART_CH_0)){
					car=UARTReceiveByte(UART_CH_0);
					if (car == '\n') car='\r';
				    	UARTTransmitByte(car, UART_CH_0);
					swim_put_char(&win1[0],car);
				}
			
				if (TSGetTouch(1, &ts_data)) {
					TouchProcess(&ts_data, &screen);
					break;
				}

			}
			break;

		case 2:
			LCD_Change_Page(NULL,2);

			while(screen==2)
			{	
				if (TSGetTouch(1, &ts_data)) {
						TouchProcess(&ts_data, &screen);
						break;
					}

			}
			break;

		case 3:
			LCD_Change_Page(NULL,3);

			while(screen == 3)
			{
				if (TSGetTouch(1, &ts_data)) TouchProcess(&ts_data, &screen);
			}

		default:
			break;

		}
	}
}


void PLLInit( void )
{
	int i;
	#ifdef RUN_FROM_RAM
		/* Remap the interrupt vectors to RAM if we are are running from RAM. */
		SCB_MEMMAP = 2;
	#endif

	/* Disable the PLL. */
	PLLCON = 0;
	PLLFEED = PLL_FEED_BYTE1;
	PLLFEED = PLL_FEED_BYTE2;

	/* Configure clock source. */
	SCS |= OSC_ENABLE;
	while( !( SCS & OSC_STAT ) );
	CLKSRCSEL = OSC_SELECT;

	/* Setup the PLL to multiply the XTAL input by 8. */
	PLLCFG = ( PLL_MUL | PLL_DIV );
	PLLFEED = PLL_FEED_BYTE1;
	PLLFEED = PLL_FEED_BYTE2;

	/* Turn on and wait for the PLL to lock... */
	PLLCON = PLL_ENABLE;
	PLLFEED = PLL_FEED_BYTE1;
	PLLFEED = PLL_FEED_BYTE2;
	/* Configurate CPU clock to divide PLL by 4... */
	CCLKCFG = CPU_CLK_DIV;
	while( !( PLLSTAT & PLL_LOCK ) );

	/* Connecting the clock. */
	PLLCON = PLL_CONNECT;
	PLLFEED = PLL_FEED_BYTE1;
	PLLFEED = PLL_FEED_BYTE2;
	while( !( PLLSTAT & PLL_CONNECTED ) );

	/*
	This code is commented out as the MAM does not work on the original revision
	LPC2368 chips.  If using Rev B chips then you can increase the speed though
	the use of the MAM.

	Setup and turn on the MAM.  Three cycle access is used due to the fast
	PLL used.  It is possible faster overall performance could be obtained by
	tuning the MAM and PLL settings.
	MAMCR = 0;
	MAMTIM = MAM_TIM_3;
	MAMCR = MAM_MODE_FULL;
	*/
}
void GPIOInit(void)
{
	// Set to inputs
	IODIR0  = 0;
	IODIR1  = 0;
	FIO0DIR = 0;
	FIO1DIR = 0;
	FIO2DIR = 0;
	FIO3DIR = 0;
	FIO4DIR = 0;

	// Enable Fast GPIO0,1
	SCS|=0x01;
	// SCS_bit.GPIOM = 1;

	// clear mask registers
	FIO0MASK =0;
	FIO1MASK =0;
	FIO2MASK =0;
	FIO3MASK =0;
	FIO4MASK = 0;

	// Reset all GPIO pins to default primary function
	PINSEL0 =0;
	PINSEL1 =0;
	PINSEL2 =0;
	PINSEL3 =0;
	PINSEL4 =0;
	PINSEL5 =0;
	PINSEL6 =0;
	PINSEL7 =0;
	PINSEL8 =0;
	PINSEL9 =0;
	PINSEL10= 0;
	PINSEL11= 0;
}





